package com.ibeeking.found.upms.g.rest.service.impl;

import com.ibeeking.found.common.constants.RoleConstant;
import com.ibeeking.found.common.entity.CurrentUser;
import com.ibeeking.found.common.enums.PublishStatusEnum;
import com.ibeeking.found.upms.g.rest.service.IGmcRoleService;
import com.ibeeking.found.upms.g.rest.service.IGmcUserRoleService;
import com.ibeeking.found.common.base.BaseDO;
import com.ibeeking.found.upms.service.common.bo.RoleBO;
import com.ibeeking.found.upms.service.common.bo.GmcUserRoleBO;
import com.ibeeking.found.upms.service.common.constants.RedisKeyConstant;
import com.ibeeking.found.upms.service.common.dos.RoleDO;
import com.ibeeking.found.upms.service.common.param.GmcRoleParam;
import com.ibeeking.found.upms.service.common.query.GmcRolePageQuery;
import com.ibeeking.found.upms.service.common.vo.GmcRolePageVO;
import com.ibeeking.found.upms.service.common.vo.RoleSelectVO;
import com.ibeeking.found.upms.service.common.vo.RoleVO;
import com.ibeeking.found.upms.service.mapper.RoleMapper;
import com.ibeeking.nematos.core.utils.SpringBeanUtil;
import com.ibeeking.nematos.exception.BusinessException;
import com.ibeeking.nematos.redis.annotation.CacheEvict;
import com.ibeeking.nematos.redis.annotation.CacheQuery;
import com.ibeeking.nematos.utils.bean.BeanUtil;
import com.ibeeking.nematos.utils.data.Collections3;
import com.ibeeking.nematos.utils.data.StringUtils;
import com.ibeeking.nematos.utils.json.JsonUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @ClassName GlobalRoleServiceImpl
 * @Description
 * @Author ibeeking
 * @Date 2020-12-02 15:29
 **/
@Service
public class GmcRoleServiceImpl extends ServiceImpl<RoleMapper, RoleDO> implements IGmcRoleService {

    @Resource
    private RoleMapper roleMapper;

    @Resource
    private IGmcUserRoleService userRoleServiceImpl;

    @Override
    public Page<GmcRolePageVO> pageList(GmcRolePageQuery gmcRolePageQuery) {
        LambdaQueryWrapper<RoleDO> queryWrapper = new LambdaQueryWrapper<>(RoleDO.class);
        queryWrapper.orderByAsc(RoleDO::getSort).orderByDesc(BaseDO::getCreateTime);

        if (null != gmcRolePageQuery.getPublishStatus()) {
            queryWrapper.eq(RoleDO::getPublishStatus, gmcRolePageQuery.getPublishStatus());
        }

        if (StringUtils.isNotBlank(gmcRolePageQuery.getRoleType())) {
            queryWrapper.eq(RoleDO::getRoleType, gmcRolePageQuery.getRoleType());
        }

        if (StringUtils.isNotBlank(gmcRolePageQuery.getCode())) {
            queryWrapper.like(RoleDO::getCode, gmcRolePageQuery.getCode());
        }

        if (StringUtils.isNotBlank(gmcRolePageQuery.getName())) {
            queryWrapper.like(RoleDO::getName, gmcRolePageQuery.getName());
        }

        Page<RoleDO> page = roleMapper.selectPage(new Page<>(gmcRolePageQuery.getPageNum(), gmcRolePageQuery.getPageSize()), queryWrapper);
        Page<GmcRolePageVO> result = BeanUtil.convertPage(page, GmcRolePageVO.class);
        /*if (Collections3.isEmpty(result.getRecords())) {
            return result;
        }
        //查询角色类型名称
        ResponseResult<List<DictDTO>> responseResult = globalFeignClient.queryDictByType("globalRoleType");
        Map<String, String> dictMap = new HashMap<>();
        if (Collections3.isEmpty(responseResult.getData())) {
            dictMap = responseResult.getData().stream().collect(Collectors.toMap(DictDTO::getValue, DictDTO::getLabel));
        }
        Map<String, String> finalDictMap = dictMap;
        dictMap = null;
        result.getRecords().forEach(key -> {
            key.setRoleTypeName(null != finalDictMap.get(key.getRoleType()) ? finalDictMap.get(key.getRoleType()) : "");

        });*/
        return result;
    }

    @Override
    public Boolean add(GmcRoleParam gmcRoleParam) {
        IGmcRoleService bean = SpringBeanUtil.getBean(IGmcRoleService.class);
       Long id1 = bean.checkCode(gmcRoleParam.getCode());
        if (null != id1) {
            throw new BusinessException("当前角色编码已存在");
        }
        Long id2 = bean.checkName(gmcRoleParam.getName());
        if (null != id2) {
            throw new BusinessException("当前角色名称已存在");
        }
        RoleDO roleDO = BeanUtil.convertBean(gmcRoleParam, RoleDO.class);

        roleDO.setCreateTime(LocalDateTime.now());
        roleDO.setModifyTime(LocalDateTime.now());
        return roleMapper.insert(roleDO) > 0;
    }

    @CacheEvict(cacheName = RedisKeyConstant.MODULE_G + RedisKeyConstant.ROLE, key = "#param.id")
    @Override
    public Boolean modify(GmcRoleParam param) {
        IGmcRoleService bean = SpringBeanUtil.getBean(IGmcRoleService.class);
        Long id1 = bean.checkName(param.getName());
        if (null != id1 && !id1.equals(param.getId())) {
            throw new BusinessException("当前角色名称已存在");
        }

        Long id2 = bean.checkCode(param.getCode());
        if (null != id2 && !id2.equals(param.getId())) {
            throw new BusinessException("当前角色编码已存在");
        }
        RoleDO roleDO = BeanUtil.convertBean(param, RoleDO.class);

        roleDO.setModifyTime(LocalDateTime.now());
        return roleMapper.updateById(roleDO) > 0;
    }

    @Override
    public RoleVO view(Long id) {
        RoleBO roleBO = SpringBeanUtil.getBean(IGmcRoleService.class).queryById(id);
       /* if (null != roleBO) {
            RoleVO roleVO = BeanUtil.convertBean(roleBO, RoleVO.class);
            //查询角色类型名称
            ResponseResult<DictDTO> responseResult = globalFeignClient.queryDictLable("globalRoleType", roleVO.getRoleType());
            if (null != responseResult.getData()) {
                roleVO.setRoleTypeName(responseResult.getData().getLabel());
            }
            return roleVO;
        }*/
        return BeanUtil.convertBean(roleBO, RoleVO.class);
    }

    @CacheQuery(cacheName = RedisKeyConstant.MODULE_G + RedisKeyConstant.ROLE, key = "#id", expires = RedisKeyConstant.MONTH)
    @Override
    public RoleBO queryById(Long id) {
        RoleDO roleDO = roleMapper.selectById(id);
        return BeanUtil.convertBean(roleDO, RoleBO.class);
    }


    @CacheEvict(cacheName = RedisKeyConstant.MODULE_G + RedisKeyConstant.ROLE, key = "#id")
    @Override
    public Boolean changeStatus(Long id, Integer status, Long userId) {
        RoleDO roleDO = new RoleDO();
        roleDO.setId(id);
        roleDO.setPublishStatus(status);
        if (administrator(id)) {
            throw new BusinessException("超级管理员不允许禁用");
        }
        roleDO.setModifyBy(userId);
        roleDO.setModifyTime(LocalDateTime.now());
        return roleMapper.updateById(roleDO) > 0;
    }

    @CacheEvict(cacheName = RedisKeyConstant.MODULE_G + RedisKeyConstant.ROLE, key = "#id")
    @Override
    public Boolean del(Long id) {
        if (administrator(id)) {
            throw new BusinessException("超级管理员不允许删除");
        }
        return roleMapper.deleteById(id) > 0;
    }

    @Override
    public Long checkCode(String roleCode) {
        RoleDO roleDO = roleMapper.selectOne(new LambdaQueryWrapper<>(RoleDO.class).eq(RoleDO::getCode, roleCode));
        return null != roleDO ? roleDO.getId() : null;
    }

    @Override
    public Long checkName(String roleName) {
        RoleDO roleDO = roleMapper.selectOne(new LambdaQueryWrapper<>(RoleDO.class).eq(RoleDO::getName, roleName));
        return null != roleDO ? roleDO.getId() : null;
    }

    @Override
    public List<RoleSelectVO> selectRoleList(CurrentUser currentUser) {
        Boolean flag = SpringBeanUtil.getBean(IGmcRoleService.class).checkIsAdministrator(currentUser.getRoleIds());
        List<RoleDO> roleDos = roleMapper.selectList(new LambdaQueryWrapper<>(RoleDO.class)
                .eq(RoleDO::getPublishStatus, PublishStatusEnum.ENABLE.getValue())
                .orderByAsc(RoleDO::getSort)
                .orderByDesc(BaseDO::getCreateTime)
        );
        if (Collections3.isEmpty(roleDos)) {
            return Collections3.emptyList();
        }
        if (flag) {
            return JsonUtils.jsonToList(roleDos, RoleSelectVO.class);
        } else {
            List<Long> roleIds = currentUser.getRoleIds();
            if (Collections3.isEmpty(currentUser.getRoleIds())) {
                return Collections3.emptyList();
            }
            List<RoleDO> result = roleDos.stream().filter(roleDO -> roleIds.contains(roleDO.getId())).collect(Collectors.toList());
            return JsonUtils.jsonToList(result, RoleSelectVO.class);
        }
    }

    @Override
    public List<String> queryUserIdsByRoleId(Long roleId) {
        List<GmcUserRoleBO> gmcUserRoleBOS = userRoleServiceImpl.queryUserRoleByRoleId(roleId);
        if (Collections3.isEmpty(gmcUserRoleBOS)) {
            return Collections3.emptyList();
        }
        return gmcUserRoleBOS.parallelStream().map(userRoleBO -> String.valueOf(userRoleBO.getUserId())).distinct().collect(Collectors.toList());
    }

    @Override
    public Boolean checkIsAdministrator(Long roleId) {
        return administrator(roleId);
    }

    @Override
    public Boolean checkIsAdministrator(List<Long> roleIds) {
        if (Collections3.isEmpty(roleIds)) {
            return false;
        }
        Integer count = roleMapper.selectCount(new LambdaQueryWrapper<>(RoleDO.class)
                .eq(RoleDO::getPublishStatus, PublishStatusEnum.ENABLE.getValue())
                .eq(RoleDO::getCode, RoleConstant.ADMINISTRATOR)
                .in(BaseDO::getId, roleIds)
        );
        return count > 0;
    }

    @CacheQuery(cacheName = RedisKeyConstant.MODULE_G + RedisKeyConstant.ROLE_ADMINISTRATOR, key = "#administrator", expires = RedisKeyConstant.MONTH)
    @Override
    public Long selectAdministratorId() {
        RoleDO roleDO = roleMapper.selectOne(new LambdaQueryWrapper<>(RoleDO.class).eq(RoleDO::getCode, RoleConstant.ADMINISTRATOR));
        return roleDO.getId();
    }

    private Boolean administrator(Long id) {
        RoleBO roleBO = SpringBeanUtil.getBean(IGmcRoleService.class).queryById(id);
        return RoleConstant.ADMINISTRATOR.equalsIgnoreCase(roleBO.getCode());
    }
}
